package com.xnyzc.lhy.task.fallback.mis;

import com.alibaba.fastjson.JSON;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.task.entity.demo.ATimes;
import com.xnyzc.lhy.task.entity.statistical.MongoStatisticalQueryRes;
import com.xnyzc.lhy.task.entity.statistical.OaSysStaticalAnalyst;
import com.xnyzc.lhy.task.entity.statistical.StatisticalData;
import com.xnyzc.lhy.task.fegin.statistics.IndexOrderStatisticsService;
import com.xnyzc.lhy.task.mapper.sys.OaCOrderPersonalMapper;
import com.xnyzc.lhy.task.mapper.sys.OaSysStaticalAnalystMapper;
import com.xnyzc.lhy.task.mapper.sys.OaSysVehicleMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DecimalFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Transactional
@Service
public class QuartzIndexStatisticsFallback implements IndexOrderStatisticsService {

    private final String TIME_CONDITION_NAME = "timestamp";
    private final String APPOINTMENT_CONDITION_NAME = "appointmentTime";
    private final String MILEAGES_CONDITION_NAME = "mileage";

    private final String INQUIRES_COUNT_NAME = "inquiriesCount";
    private final String DEAL_COUNT_NAME = "dealCount";
    private final String TADIO_COUNT_NAME = "tadio";
    private final int MILEAGES = 21;
    private final int HOURS = 24;
    private final String STATISTICAL_HOURS = "statisticalHours";

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private OaSysStaticalAnalystMapper oaSysStaticalAnalystMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void saveIndexOrderStaticalData(Long computeDate) {
        Long startTime = (Long) redisTemplate.opsForHash().get(STATISTICAL_HOURS, STATISTICAL_HOURS);
        if(CheckUtil.objIsEmpty(startTime)){
            startTime = System.currentTimeMillis()-5*60*1000;
        }
        Long endTime = startTime+5*60*1000;
        redisTemplate.opsForHash().delete(STATISTICAL_HOURS,STATISTICAL_HOURS);
        //测试统计1分钟内的数据
        getCurrentInquiresCount(startTime, endTime);
        getAppointInquiresCount(startTime, endTime);
        getMileageInquiresCount(startTime, endTime);
        redisTemplate.opsForHash().putIfAbsent(STATISTICAL_HOURS,STATISTICAL_HOURS,endTime);
    }
    //当前时间询价统计图的方法
    private void getCurrentInquiresCount(long startTime, long endTime) {
        List<MongoStatisticalQueryRes> inquiresCountFromMongo = getDataCountFromMongo(startTime, endTime, TIME_CONDITION_NAME, false);
        List<MongoStatisticalQueryRes> dealCountFromMongo = getDataCountFromMongo(startTime, endTime, TIME_CONDITION_NAME, true);
        //处理询价次数
        inquiriesCountHandler(inquiresCountFromMongo, TIME_CONDITION_NAME);
        //处理成交次数
        dealCountHandler(dealCountFromMongo, TIME_CONDITION_NAME);
    }

    //预约时间询价统计图的方法
    private void getAppointInquiresCount(long startTime, long endTime) {
        List<MongoStatisticalQueryRes> inquiresCountFromMongo = getDataCountFromMongo(startTime, endTime, APPOINTMENT_CONDITION_NAME, false);
        List<MongoStatisticalQueryRes> dealCountFromMongo = getDataCountFromMongo(startTime, endTime, APPOINTMENT_CONDITION_NAME, true);
        HashMap<String, Object> res = new HashMap<>();
        //处理询价次数
        inquiriesCountHandler(inquiresCountFromMongo, APPOINTMENT_CONDITION_NAME);
        //处理成交次数
        dealCountHandler(dealCountFromMongo, APPOINTMENT_CONDITION_NAME);
    }

    //预约时间里里程询价统计图的方法
    private void getMileageInquiresCount(long startTime, long endTime) {
        List<MongoStatisticalQueryRes> inquiresCountFromMongo = getDataCountFromMongo(startTime, endTime, MILEAGES_CONDITION_NAME, false);
        List<MongoStatisticalQueryRes> dealCountFromMongo = getDataCountFromMongo(startTime, endTime, MILEAGES_CONDITION_NAME, true);
        //处理询价次数
        mileageCountFunction(inquiresCountFromMongo);
        //处理成交次数
        mileageDealCountFunction(dealCountFromMongo);
    }

    //从mongo获取当前前3小时中第一个小时的数据
    private List<MongoStatisticalQueryRes> getDataCountFromMongo(long startTime, long endTime, String conditionName, boolean isDeal) {
        List<AggregationOperation> operations = new ArrayList<>();
        if (isDeal) {
            operations.add(Aggregation.match(Criteria.where("orderCreateTime").gte(startTime).lt(endTime).and("isDeal").is(1)
                    .and("mileageCount").ne("").ne(null)));
        } else {
            operations.add(Aggregation.match(Criteria.where("timestamp").gte(startTime).lt(endTime)
                    .and("mileageCount").ne("").ne(null)));
        }
        if (conditionName.equals(APPOINTMENT_CONDITION_NAME)) {
            operations.add(Aggregation.group("appointmentHourTime", "cityCode", "channel").count().as("count"));
            operations.add(Aggregation.project("appointmentHourTime", "cityCode", "channel", "count"));
        } else if (conditionName.equals(MILEAGES_CONDITION_NAME)) {
            operations.add(Aggregation.group("mileageCount", "appointmentDayTime", "cityCode", "channel").count().as("count"));
            operations.add(Aggregation.project("mileageCount", "appointmentDayTime", "cityCode", "channel", "count"));
        } else {
            operations.add(Aggregation.group("timesHourTamp", "cityCode", "channel").count().as("count"));
            operations.add(Aggregation.project("timesHourTamp", "cityCode", "channel", "count"));
        }

        Aggregation aggregation = Aggregation.newAggregation(operations);
        AggregationResults<MongoStatisticalQueryRes> data = mongoTemplate.aggregate(aggregation, "priceStatisticalData", MongoStatisticalQueryRes.class);
        List<MongoStatisticalQueryRes> results = data.getMappedResults();
        return results;
    }

    //时间处理询价次数
    private void inquiriesCountHandler(List<MongoStatisticalQueryRes> inquiresCountFromMongo, String timeFlag) {
        if (CheckUtil.objIsEmpty(inquiresCountFromMongo)) {
            return;
        }
        for (MongoStatisticalQueryRes mongoStatisticalQueryRes : inquiresCountFromMongo) {
            HashMap<String, Object> res = new HashMap<>();
            int[] inquiresCounts = new int[HOURS];
            int[] dealCounts = new int[HOURS];
            int hour = 0;
            String date = "";
            OaSysStaticalAnalyst existData = null;
            //如果数据库存在 则更新数据；不存在则直接插入
            Date time = null;
            //根据渠道和城市查询数据库中是否存在数据
            OaSysStaticalAnalyst existDataFromSql = oaSysStaticalAnalystMapper.queryIsExistData(mongoStatisticalQueryRes.getChannel(), mongoStatisticalQueryRes.getCityCode(), null, null);
            if (timeFlag.equals(TIME_CONDITION_NAME)) {
                if (CheckUtil.objIsNotEmpty(existDataFromSql)) {
                    time = existDataFromSql.getCreateTime();
                }
                hour = DateUtil.getTodayHour(new Date(mongoStatisticalQueryRes.getTimesHourTamp()));
                date = DateUtil.convertToStringCustom(new Date(mongoStatisticalQueryRes.getTimesHourTamp()), "yyyy-MM-dd");
                existData = oaSysStaticalAnalystMapper.queryIsExistData(mongoStatisticalQueryRes.getChannel(), mongoStatisticalQueryRes.getCityCode(), null, date);
            } else {
                if (CheckUtil.objIsNotEmpty(existDataFromSql)) {
                    time = existDataFromSql.getAppointment();
                }
                hour = DateUtil.getTodayHour(new Date(mongoStatisticalQueryRes.getAppointmentHourTime()));
                date = DateUtil.convertToStringCustom(new Date(mongoStatisticalQueryRes.getAppointmentHourTime()), "yyyy-MM-dd");
                //根据渠道、城市和时间查询数据库中是否存在数据
                existData = oaSysStaticalAnalystMapper.queryIsExistData(mongoStatisticalQueryRes.getChannel(), mongoStatisticalQueryRes.getCityCode(), date, null);
            }
            if (existData != null) {
                //更新询价；
                String timeDatas = "";
                if (timeFlag.equals(TIME_CONDITION_NAME)) {
                    timeDatas = existData.getCtimeDatas();
                } else {
                    timeDatas = existData.getAtimeDatas();
                }
                HashMap old = JSON.parseObject(timeDatas, HashMap.class);
                List<Integer> oldInquires = JSON.parseArray(JSON.toJSONString(old.get(INQUIRES_COUNT_NAME)), Integer.class);
                List<Integer> oldDeal = JSON.parseArray(JSON.toJSONString(old.get(DEAL_COUNT_NAME)), Integer.class);
                oldInquires.set(hour, oldInquires.get(hour) .intValue()+mongoStatisticalQueryRes.getCount().intValue());
                old.put(INQUIRES_COUNT_NAME, oldInquires);
                old.put(DEAL_COUNT_NAME, oldDeal);
                String ress = JSON.toJSONString(old);
                if (timeFlag.equals(TIME_CONDITION_NAME)) {
                    existData.setCtimeDatas(ress);
                } else {
                    existData.setAtimeDatas(ress);
                }
                int update = oaSysStaticalAnalystMapper.updateById(existData);
                if (update != 1) {
                    throw PangException.create(EErrorCode.updateWalletFailure);
                }
            } else if (CheckUtil.objIsNotEmpty(existDataFromSql) && CheckUtil.objIsEmpty(time)) {
                //相同城市和渠道 时间为null 也更新数据
                inquiresCounts[hour] = mongoStatisticalQueryRes.getCount().intValue();
                res.put(INQUIRES_COUNT_NAME, inquiresCounts);
                res.put(DEAL_COUNT_NAME, dealCounts);
                String ress = JSON.toJSONString(res);
                if (timeFlag.equals(TIME_CONDITION_NAME)) {
                    existDataFromSql.setCreateTime(DateUtil.getDateStringShort(date));
                    existDataFromSql.setCtimeDatas(ress);
                } else {
                    existDataFromSql.setAppointment(DateUtil.getDateStringShort(date));
                    existDataFromSql.setAtimeDatas(ress);
                }
                int update = oaSysStaticalAnalystMapper.updateById(existDataFromSql);
                if (update != 1) {
                    throw PangException.create(EErrorCode.updateWalletFailure);
                }
            } else {
                OaSysStaticalAnalyst analyst = new OaSysStaticalAnalyst();
                //数据库不存在数据 则直接插入
                inquiresCounts[hour] = mongoStatisticalQueryRes.getCount().intValue();
                res.put(INQUIRES_COUNT_NAME, inquiresCounts);
                res.put(DEAL_COUNT_NAME, dealCounts);
                String ress = JSON.toJSONString(res);
                analyst.setCityCode(mongoStatisticalQueryRes.getCityCode());
                analyst.setChannel(mongoStatisticalQueryRes.getChannel());
                if (timeFlag.equals(TIME_CONDITION_NAME)) {
                    analyst.setCtimeDatas(ress);
                    analyst.setCreateTime(DateUtil.getDateStringShort(date));
                } else {
                    analyst.setAtimeDatas(ress);
                    analyst.setAppointment(DateUtil.getDateStringShort(date));
                }
                analyst.setUpdateTime(new Date());
                analyst.setId(IDUtil.nextId());
                int insert = oaSysStaticalAnalystMapper.insert(analyst);
                if (insert != 1) {
                    throw PangException.create(EErrorCode.addError);
                }
            }
        }
    }

    //处理成交次数
    private void dealCountHandler(List<MongoStatisticalQueryRes> dealCountFromMongo, String timeFlag) {
        if (CheckUtil.objIsEmpty(dealCountFromMongo)) {
            return;
        }
        int hour = 0;
        String date = "";
        OaSysStaticalAnalyst existData = null;
        for (MongoStatisticalQueryRes dealQueryRes : dealCountFromMongo) {
            //如果数据库存在 则合并更新询价 直接赋值成交；不存在则直接插入
            if (timeFlag.equals(APPOINTMENT_CONDITION_NAME)) {
                hour = DateUtil.getTodayHour(new Date(dealQueryRes.getAppointmentHourTime()));
                date = DateUtil.convertToStringCustom(new Date(dealQueryRes.getAppointmentHourTime()), "yyyy-MM-dd");
                //根据渠道、城市和时间查询数据库中是否已经存在数据
                existData = oaSysStaticalAnalystMapper.queryIsExistData(dealQueryRes.getChannel(), dealQueryRes.getCityCode(), date, null);
            } else {
                hour = DateUtil.getTodayHour(new Date(dealQueryRes.getTimesHourTamp()));
                date = DateUtil.convertToStringCustom(new Date(dealQueryRes.getTimesHourTamp()), "yyyy-MM-dd");
                //根据渠道、城市和时间查询数据库中是否已经存在数据
                existData = oaSysStaticalAnalystMapper.queryIsExistData(dealQueryRes.getChannel(), dealQueryRes.getCityCode(), null, date);
            }
            if (existData != null) {
                //则合并更新询价 直接赋值成交；
                String timeDatas = "";
                if (timeFlag.equals(APPOINTMENT_CONDITION_NAME)) {
                    timeDatas = existData.getAtimeDatas();
                } else {
                    timeDatas = existData.getCtimeDatas();
                }
                HashMap old = JSON.parseObject(timeDatas, HashMap.class);
                List<Integer> oldInquires = JSON.parseArray(JSON.toJSONString(old.get(INQUIRES_COUNT_NAME)), Integer.class);
                List<Integer> oldDeal = JSON.parseArray(JSON.toJSONString(old.get(DEAL_COUNT_NAME)), Integer.class);
                oldDeal.set(hour, oldDeal.get(hour).intValue() + dealQueryRes.getCount().intValue());
                old.put(INQUIRES_COUNT_NAME, oldInquires);
                old.put(DEAL_COUNT_NAME, oldDeal);
                String ress = JSON.toJSONString(old);
                if (timeFlag.equals(APPOINTMENT_CONDITION_NAME)) {
                    existData.setAtimeDatas(ress);
                } else {
                    existData.setCtimeDatas(ress);
                }
                int update = oaSysStaticalAnalystMapper.updateById(existData);
                if (update != 1) {
                    throw PangException.create(EErrorCode.updateWalletFailure);
                }
            }
        }
    }

    //里程询价次数处理方法
    private void mileageCountFunction(List<MongoStatisticalQueryRes> inquiresCountFromMongo) {
        for (MongoStatisticalQueryRes mongoStatisticalQueryRes : inquiresCountFromMongo) {
            HashMap<String, Object> res = new HashMap<>();
            int[] inquiresCounts = new int[MILEAGES];
            int[] dealCounts = new int[MILEAGES];
            //如果数据库存在 则合并更新询价 直接赋值成交；不存在则直接插入
            if (CheckUtil.objIsEmpty(mongoStatisticalQueryRes.getAppointmentDayTime())) {
                continue;
            }
            int mileageCount = mongoStatisticalQueryRes.getMileageCount();
            String date = DateUtil.convertToStringCustom(new Date(mongoStatisticalQueryRes.getAppointmentDayTime()), "yyyy-MM-dd");
            OaSysStaticalAnalyst existData = oaSysStaticalAnalystMapper.queryIsExistData(mongoStatisticalQueryRes.getChannel(), mongoStatisticalQueryRes.getCityCode(), date, null);
            if (CheckUtil.objIsNotEmpty(existData)) {
                //则合并更新询价 直接赋值成交；
                if (CheckUtil.objIsNotEmpty(existData.getMileageDatas())) {
                    String mileageDatas = existData.getMileageDatas();
                    HashMap old = JSON.parseObject(mileageDatas, HashMap.class);
                    List<Integer> oldInquires = JSON.parseArray(JSON.toJSONString(old.get(INQUIRES_COUNT_NAME)), Integer.class);
                    List<Integer> oldDeal = JSON.parseArray(JSON.toJSONString(old.get(DEAL_COUNT_NAME)), Integer.class);
                    oldInquires.set(mileageCount, oldInquires.get(mileageCount).intValue() + mongoStatisticalQueryRes.getCount().intValue());
                    old.put(INQUIRES_COUNT_NAME, oldInquires);
                    old.put(DEAL_COUNT_NAME, oldDeal);
                    String ress = JSON.toJSONString(old);
                    existData.setMileageDatas(ress);
                } else {
                    inquiresCounts[mileageCount] = mongoStatisticalQueryRes.getCount().intValue();
                    res.put(INQUIRES_COUNT_NAME, inquiresCounts);
                    res.put(DEAL_COUNT_NAME, dealCounts);
                    String ress = JSON.toJSONString(res);
                    existData.setMileageDatas(ress);
                }
                int update = oaSysStaticalAnalystMapper.updateById(existData);
                if (update != 1) {
                    throw PangException.create(EErrorCode.updateWalletFailure);
                }
            }
        }
    }

    //里程成交次数处理方法
    private void mileageDealCountFunction(List<MongoStatisticalQueryRes> dealCountFromMongo) {
        for (MongoStatisticalQueryRes dealQueryRes : dealCountFromMongo) {
            //如果数据库存在 则合并更新询价 直接赋值成交；不存在则直接插入
            if (CheckUtil.objIsEmpty(dealQueryRes.getAppointmentDayTime())) {
                continue;
            }
            int mileageCount = dealQueryRes.getMileageCount();
            String date = DateUtil.convertToStringCustom(new Date(dealQueryRes.getAppointmentDayTime()), "yyyy-MM-dd");
            OaSysStaticalAnalyst existData = oaSysStaticalAnalystMapper.queryIsExistData(dealQueryRes.getChannel(), dealQueryRes.getCityCode(), date, null);
            if (existData != null) {
                //则合并更新询价 直接赋值成交；
                String atimeDatas = existData.getMileageDatas();
                HashMap old = JSON.parseObject(atimeDatas, HashMap.class);
                List<Integer> oldInquires = JSON.parseArray(JSON.toJSONString(old.get(INQUIRES_COUNT_NAME)), Integer.class);
                List<Integer> oldDeal = JSON.parseArray(JSON.toJSONString(old.get(DEAL_COUNT_NAME)), Integer.class);
                oldDeal.set(mileageCount, oldDeal.get(mileageCount).intValue() + dealQueryRes.getCount().intValue());
                old.put(INQUIRES_COUNT_NAME, oldInquires);
                old.put(DEAL_COUNT_NAME, oldDeal);
                String ress = JSON.toJSONString(old);
                existData.setMileageDatas(ress);
                int update = oaSysStaticalAnalystMapper.updateById(existData);
                if (update != 1) {
                    throw PangException.create(EErrorCode.updateWalletFailure);
                }
            }
        }
    }
}
